﻿#ifndef CLIENTSOCKET_H
#define CLIENTSOCKET_H

#include <QObject>
#include <QTcpSocket>
#include <QFile>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QThread>
#include <QTimer>

class ClientSocket : public QObject
{
    Q_OBJECT
public:
    explicit ClientSocket(QObject *parent = nullptr);
    ~ClientSocket();

    void CheckConnected();
    bool SendPackage(const char* pBuffer, qint64 length);
signals:
    void signalStatus(const quint8 &state);         //服务器状态：掉线 or 连接，还有登陆，注册也由这个发送，会造成逻辑歧义，应该分开
    void sigUserInfo(const QJsonObject&);           //当前登录用户的个人信息
    void sigFriendList(const QJsonObject&);         //更新好友列表
    void sigUpdateUserStatus(int id,int status);    //好友状态（在线、离线）更新
    void sigUpdateFriendInfo(const QJsonObject&);   //好友个人信息更新
    void sigFindUser(const QJsonObject&);           //查找好友结果
    void sigRequestAddUser(const QJsonObject&);     //请求添加好友
    void sigReplyUserExisted(int userid,QString username);      //服务端回应该用户已经是您的好友
    void sigDelFriend(int userid);                              //删除好友，发送给客户端通知界面更改
    void sigAddUserResult(QString username,int accept);         //添加好友结果
    void sigChatMsg(const QJsonObject&,int senderid);           //文字聊天消息
public:
    QTcpSocket*         m_pTcpSocket;
    QTimer*             m_timer;                       //心跳定时器
    QTimer*             m_timerRetry;                  //心跳定时器
private:
    int                 m_seq;                         //当前数据包序列号
    QByteArray          m_buffer;                      //缓存上一次或多次的未处理的数据,重新粘包
    QByteArray          m_writeBuffer;
    bool                m_isOkConnect;                 //标志是否连接上服务器
    int                 m_retryDelayMs;                //掉线重连
    static const int    s_kMaxRetryDelayMs = 30*1000;
    static const int    s_kInitRetryDelayMs = 500;
private:
    void initConnection();
    bool Process(const char* inbuf, size_t length);
    void OnRegisterResult(const char* data,size_t length);
    void OnLoginResult(const char* data,size_t length);
    void OnUpdateUserInfo(const char* data,size_t length);
    void OnUpdateUserStatus(int userid, const char* data, size_t length);
    void OnGotFriendList(const char* data,size_t length);
    void OnFindUser(const char* data,size_t length);
    void OnOperateFriend(const char* data,size_t length);
    void OnChatMsg(const char* data, size_t length, int senderid);
    void ParseDataToJson(const char* data, size_t length, QJsonObject& jsonObj);

public slots:
    void SltSend(int cmd, const QJsonObject& json);                         //发送消息
    void SltSendtoTargetid(int cmd,const QJsonObject& json,int targetid);

    void ConnectToHost();           //连接服务器
    void CloseConnected();
private slots:
    void retryConnect();            //自动重连
    void SltDisconnected();         // 与服务器断开链接
    void SltConnected();            // 连接上服务器
    void SltReadyRead();            // tcp消息处理
    void SltHeartbeat();            //心跳协议
};

#endif // CLIENTSOCKET_H
